home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / makedev-.5 / makedev- / makedev-1.5 / parser.syn < prev    next >
Text File  |  1995-03-25  |  10KB  |  354 lines

  1. {
  2. /*
  3.  * parser.c: Parser for MAKEDEV, a program to create entries in /dev.
  4.  *
  5.  * Based on the MAKEDEV shell script, version 2.0, distributed with
  6.  * util-linux 1.10 and written by Nick Holloway. 
  7.  *
  8.  * A number of bugs were fixed, and some additional features added.
  9.  * Written 10-Dec-94 by David A. Holland, dholland@husc.harvard.edu
  10.  * Rik Faith (faith@cs.unc.edu) contributed ideas and patches.
  11.  *
  12.  * Copyright 1994, 1995. All rights reserved. 
  13.  * See the file LEGAL.NOTICE for conditions of redistribution.
  14.  *
  15.  * Bugs:
  16.  *    None known right now.
  17.  *
  18.  * History:
  19.  *
  20.  * Version 2: 25-Mar-95    Fixed makefile. 
  21.  *    Look for config files in ".." under testing conditions.
  22.  *    Big source split: makedev.syn -> parser.syn and devices.c.
  23.  *    Consequently, this file's version numbers aren't the same as the
  24.  *    whole program's any more.
  25.  * Version 1.4b: 25-Mar-95 Merged Rik's changes. Additional bug fixes:
  26.  *    Don't leave off the last entry in a range.
  27.  *    Parse hex digits correctly [sigh...].
  28.  *    Now we actually *use* the ishex flag.
  29.  * Version 1.4a: 26-Feb-95 Forced devinfo and makedev.cfg to be in /etc.
  30.  *                         [from faith@cs.unc.edu]
  31.  * Version 1.4: 15-Jan-95  Wrote man pages. Now reads DEVINFO.local.
  32.  * Version 1.3: 31-Dec-94  Bug fixes. Added batches. Added omits.
  33.  * Version 1.2: 11-Dec-94  Add configuration file parsing.
  34.  * Version 1.1: 11-Dec-94  Distinguish block and character devices in the
  35.  *    table of major device numbers. Changed the name and format of the
  36.  *    update cache file to include the type. It appears that the old script
  37.  *    was broken in this regard.
  38.  * Version 1.0: 10-Dec-94  Initial version.
  39.  */
  40.  
  41.  
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <stdarg.h>
  46. #include <unistd.h>
  47. #include <fcntl.h>
  48. #include <pwd.h>
  49. #include <grp.h>
  50. #include <sys/stat.h>
  51.  
  52. #include "devices.h"
  53.  
  54. }
  55. {
  56. /************************* parsing support *************************/
  57.  
  58. /*
  59.  * Don't use the built-in error printing.
  60.  */
  61. #define SYNTAX_ERROR
  62. #define PARSER_STACK_OVERFLOW
  63. #define REDUCTION_TOKEN_ERROR
  64.  
  65. void doparse(FILE *f, int filetype, const char *filename) {
  66.   char *x;
  67.   int i=0, len;
  68.   if (filetype<1 || filetype>4) crash("tried to parse a bad file type");
  69.   if (filetype!=1) { /* /proc/devices won't stat intelligently */
  70.     struct stat buf;
  71.     if (fstat(fileno(f), &buf)) crash("fstat failed?!?");
  72.     len = buf.st_size;
  73.   }
  74.   else len=1023;
  75.   x = malloc(len+1);
  76.   if (!x) crash("Out of memory");
  77.  
  78.   len = fread(x, 1, len, f);  /* it shouldn't return a short count... */
  79.   if (len<0) crash("fread failed?!?");
  80.   x[len]=0;
  81.  
  82.   init_parse();
  83.   PCB.input_code = filetype+'0';
  84.   parse();
  85.   PCB.column--; /* correct for the filetype token */
  86.   while (!PCB.exit_flag) {
  87.     PCB.input_code = x[i++];
  88.     parse();
  89.   }
  90.   if (PCB.exit_flag == AG_SYNTAX_ERROR_CODE) {
  91.     warn("syntax error: %s, line %d, column %d in file %s",
  92.          PCB.error_message, PCB.line, PCB.column, filename);
  93.     crash("Sorry, can't continue.");
  94.   }
  95.   else if (PCB.exit_flag != AG_SUCCESS_CODE) {
  96.     crash("parser stack overflow!");
  97.   }
  98. }
  99.  
  100. #define STRINGSIZE 8192
  101. static char string_space[STRINGSIZE];
  102. static int stringptr=0;
  103.  
  104. static const char *string_start(int c) {
  105.   if (stringptr>=STRINGSIZE) crash("out of string space");
  106.   return string_space[stringptr]=c, string_space+stringptr++;
  107. }
  108.  
  109. static void string_push(int c) {
  110.   if (stringptr>=STRINGSIZE) crash("out of string space");
  111.   string_space[stringptr++] = c;
  112. }
  113.  
  114. static void string_finish(void) {
  115.   string_push(0);
  116. }
  117.  
  118. }
  119. /************************* syntax begins here *************************/
  120.  
  121. /*
  122.  * We read four different file formats here:
  123.  *     /proc/devices   1
  124.  *     MAKEDEV.cache   2
  125.  *     DEVINFO         3
  126.  *     MAKEDEV.config  4
  127.  */
  128.  
  129.  
  130. [
  131.   sticky {identifier}
  132.   disregard white space
  133.   lexeme {identifier, simple eol, quoted string}
  134.   distinguish keywords {'a-z' + 'A-Z'}
  135.   event driven
  136.   parser name = parse
  137.   line numbers
  138. ]
  139.  
  140. (void) file format $
  141.   -> '1', devices
  142.   -> '2', cache
  143.   -> '3', devinfo
  144.   -> '4', config
  145.  
  146.  
  147. /************************* /proc/devices *************************/
  148.  
  149. (void) devices
  150.   -> eol?, device list..., eof
  151.  
  152. (void) device list
  153.   -> "Character devices:", eol, character device...
  154.   -> "Block devices:", eol, block device...
  155.  
  156. (void) character device
  157.   -> number:n, name:s, eol = set_major(s,YES,n);
  158.  
  159. (void) block device
  160.   -> number:n, name:s, eol = set_major(s,NO,n);
  161.  
  162. /************************* cache *************************/
  163.  
  164. (void) cache
  165.   -> eol?, cachedevice..., eof
  166.  
  167. (void) cachedevice
  168.   -> name:n, number:maj, devicetype:t, eol = updatefromcache(n,maj,t);
  169.  
  170. (char) devicetype
  171.   -> 'b'       = 'b';
  172.   -> 'c'       = 'c';
  173.   -> "block"   = 'b';
  174.   -> "char"    = 'c';
  175.  
  176. /************************* devinfo *************************/
  177.  
  178. (void) devinfo
  179.   -> eol?, device block..., eof
  180.  
  181. (void) device block
  182.   -> device header spec, '{', eol?, device decl?..., '}', eol?
  183.   -> device header spec, eol?, device decl
  184.   -> "ignore", '{', eol?, ignoramus..., '}', eol?
  185.   -> "batch", batch list, '}', eol?
  186.  
  187. (batch *) batch list
  188.   -> name:n, '{', eol?, batch item:i, eol?  = add2batch(addbatch(n), i);
  189.   -> batch list:b, [',', eol?], batch item:i, eol? = add2batch(b,i);
  190.  
  191. (const char *) batch item
  192.   -> name:n = n;
  193.  
  194. (void) ignoramus
  195.   -> name:n, eol?, [',', eol?] = ignore_procname(n);
  196.  
  197. {
  198.   static const char *cur_group=NULL, *cur_class=NULL;
  199.   static int cur_type;
  200.   static int cur_maj=0, cur_min=0, cur_bot=0, cur_top=0, ishex=0;
  201.  
  202.   static void dhsproc(const char *g, const char *p, int t, int m) {
  203.     cur_group = g;
  204.     cur_type = t;
  205.     cur_maj = get_major(p, (t=='c'), m);
  206.     cur_min = 0;
  207.     cur_bot = cur_top = ishex = 0;
  208.     if (p) addalias(p,g);
  209.   }
  210.  
  211.   static void newdev(const char *n) {
  212.     if (cur_maj<0) return;
  213.     init(n, cur_group, cur_class, cur_maj, cur_min, cur_type);
  214.   }
  215.   static void devrange(const char *n, const char *n1) {
  216.     char temp[32];
  217.     if (cur_maj<0) return;
  218.     sprintf(temp, "%s%%%c%s", n, ishex ? 'x' : 'd', n1 ? n1 : "");
  219.     initlots(temp, cur_bot, cur_top, cur_group, cur_class,
  220.          cur_maj, cur_min, cur_type);
  221.   }
  222.   static void doinitlink(const char *src, const char *tg) {
  223.     if (cur_maj>=0) initlink(src, cur_group, tg);
  224.   }
  225. }
  226.  
  227. (void) device header spec
  228.   -> devicetype:t, '(', groupname:g, '=', procname:p, ')' = dhsproc(g,p,t,-1);
  229.   -> devicetype:t, '(', groupname:g, '=', procname:p,
  230.                   ',', number:m, ')'                    = dhsproc(g,p,t,m);
  231.   -> devicetype:t, '(', groupname:g, ',', number:m, ')' = dhsproc(g,NULL,t,m);
  232.  
  233. (const char *) class
  234.   -> '(', name:classname, ')' = classname;
  235.  
  236. (void) device tail
  237.   -> class:c, ':', expr:min, eol = (cur_class=c, cur_min=min);
  238.  
  239. (void) device range
  240.   -> '[', number:a, '-', number:b, ']'       = cur_bot=a, cur_top=b, ishex=0;
  241.   -> '[', hex number:a, '-', auto hex:b, ']' = cur_bot=a, cur_top=b, ishex=1;
  242.  
  243. (void) device decl
  244.   -> devname:n,                           device tail = newdev(n);
  245.   -> devname:n, device range, devname:n1, device tail = devrange(n,n1);
  246.   -> devname:n, device range,             device tail = devrange(n,NULL);
  247.   -> devname:n, '[', letter:a, '-', letter:b,']', number:p,'/',number:m, eol =
  248.         initdisk(n, a, b, p, cur_maj, m);
  249.   -> devname:n, "->", name:tg, eol = doinitlink(n, tg);
  250.  
  251. (const char *) devname -> name:n = n;
  252. (const char *) groupname -> name:n = n;
  253. (const char *) procname -> name:n = n;
  254.  
  255.  
  256. /************************* config *************************/
  257.  
  258. (void) config
  259.   -> eol?, config decl..., eof
  260.  
  261. (void) config decl
  262.   -> class decl
  263.   -> omit decl
  264.  
  265. (void) class decl
  266.   -> "class", name:n, ':', name:o, name:g, mode:m, eol = addclass(n,o,g,m);
  267.  
  268. (void) omit decl
  269.   -> "omit", name:n, eol = make(n, M_OMIT);
  270.   -> "omit", '{', eol?, single omit..., '}', eol?
  271.  
  272. (void) single omit
  273.   -> name:n, eol?, [',', eol?] = make(n, M_OMIT);
  274.  
  275. (int) mode
  276.  -> octal number:n = n;
  277.  
  278. /************************* support *************************/
  279.  
  280. eof         = -1 + 0
  281. digit       = '0-9'
  282. letter      = 'a-z' + 'A-Z' + '-' + '_'
  283. octal digit = '0-7'
  284. qchar       = 32..126 - '\\' - '"'
  285.  
  286. (void) white space
  287.  -> ' ' + '\t' + '\r'
  288.  -> "/*", ~eof?..., "*/"
  289.  
  290.  
  291. (void) eol
  292.  -> simple eol...
  293.  
  294. (void) simple eol
  295.  -> [{"//" | '#'}, ~'\n'?...], '\n'
  296.  
  297. (const char *) name
  298.   -> identifier:s = string_finish(), s;
  299.   -> quoted string:s = s;
  300.  
  301. (const char *) identifier
  302.   -> letter:c                       = string_start(c);
  303.   -> identifier:s, letter+digit:c   = string_push(c), s;
  304.  
  305. (const char *) quoted string
  306.   -> '"', qstring:s, '"' = string_finish(), s;
  307.  
  308. (const char *) qstring
  309.   -> qstring char:c            = string_start(c);
  310.   -> qstring:s, qstring char:c = string_push(c), s;
  311.  
  312. (char) qstring char
  313.   -> qchar:c     = c;
  314.   -> '\\', '\\'  = '\\';
  315.   -> '\\', '"'   = '"';
  316.  
  317. (int) number
  318.   -> digit:d           = d-'0';
  319.   -> number:n, digit:d = n*10 + d-'0';
  320.  
  321. (int) hex number
  322.   -> {"0x" | "0X"}, hex digit:d    =d;
  323.   -> hex number:n, hex digit:d     =16*n+d;
  324.  
  325. (int) auto hex
  326.   -> hex digit:d    =d;
  327.   -> auto hex:n, hex digit:d     =16*n+d;
  328.  
  329.  
  330. (int) hex digit
  331.   -> digit:d     = d-'0';
  332.   -> 'a-f':d     = 10 + d-'a';
  333.   -> 'A-F':d     = 10 + d-'A';
  334.  
  335. (int) octal number
  336.  -> octal digit:d                  = d-'0';
  337.  -> octal number:n, octal digit:d  = n*8+d-'0';
  338.  
  339. (int) expr
  340.  -> term
  341.  -> expr:x, '+', term:t         =x+t;
  342.  -> expr:x, '-', term:t         =x-t;
  343.  
  344. (int) term
  345.  -> factor
  346.  -> term:t, '*', factor:f       =t*f;
  347. // -> term:t, '/', factor:f       =t/f;
  348.  
  349. (int) factor
  350.  -> number
  351.  -> hex number
  352.  -> '-', factor:f               =-f;
  353.  -> '(', expr:x, ')'            =x;
  354.